import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Param,
  Body,
  Query,
  HttpException,
  HttpStatus,
  UseGuards,
} from '@nestjs/common'
import { CrudService } from '../services/crud.service'
import { MetadataService } from '../../metadata/services/metadata.service'
import { ApiTags, ApiOperation, ApiBody } from '@nestjs/swagger'
import { Permissions } from 'src/common/decorators/permissions.decorator'

/**
 * 动态CRUD控制器
 * 支持任意模型的增删改查，自动字段校验和权限守卫
 */
@ApiTags('动态CRUD')
@Controller('data/:model')
export class DynamicCrudController {
  constructor(
    private readonly crudService: CrudService<any>,
    private readonly metadataService: MetadataService,
  ) {}

  /** 获取列表 */
  @Get()
  @ApiOperation({ summary: '获取模型数据列表' })
  @Permissions('crud:list')
  async list(@Param('model') model: string, @Query() query: any) {
    const schema = await this.metadataService.getModel(model)
    if (!schema) throw new HttpException('模型不存在', HttpStatus.NOT_FOUND)
    // 数据权限过滤可在此处集成
    return this.crudService.list(model, query)
  }

  /** 获取详情 */
  @Get(':id')
  @ApiOperation({ summary: '获取单条数据' })
  @Permissions('crud:read')
  async detail(@Param('model') model: string, @Param('id') id: string) {
    const schema = await this.metadataService.getModel(model)
    if (!schema) throw new HttpException('模型不存在', HttpStatus.NOT_FOUND)
    return this.crudService.detail(model, id)
  }

  /** 新增 */
  @Post()
  @ApiOperation({ summary: '新增数据' })
  @ApiBody({ schema: { example: { title: 'xxx', content: 'yyy' } } })
  @Permissions('crud:create')
  async create(@Param('model') model: string, @Body() data: any) {
    const schema = await this.metadataService.getModel(model)
    if (!schema) throw new HttpException('模型不存在', HttpStatus.NOT_FOUND)
    // 字段校验
    validateFields(schema, data)
    return this.crudService.create(model, data)
  }

  /** 更新 */
  @Put(':id')
  @ApiOperation({ summary: '更新数据' })
  @Permissions('crud:update')
  async update(@Param('model') model: string, @Param('id') id: string, @Body() data: any) {
    const schema = await this.metadataService.getModel(model)
    if (!schema) throw new HttpException('模型不存在', HttpStatus.NOT_FOUND)
    validateFields(schema, data, true)
    return this.crudService.update(model, id, data)
  }

  /** 删除 */
  @Delete(':id')
  @ApiOperation({ summary: '删除数据' })
  @Permissions('crud:delete')
  async remove(@Param('model') model: string, @Param('id') id: string) {
    const schema = await this.metadataService.getModel(model)
    if (!schema) throw new HttpException('模型不存在', HttpStatus.NOT_FOUND)
    return this.crudService.remove(model, id)
  }
}

/**
 * 字段校验工具
 * 根据模型元数据自动校验类型和必填
 */
function validateFields(schema: any, data: any, partial = false) {
  for (const field of schema.fields) {
    if (!partial && field.required && (data[field.name] === undefined || data[field.name] === null)) {
      throw new HttpException(`字段 ${field.label || field.name} 必填`, HttpStatus.BAD_REQUEST)
    }
    if (data[field.name] !== undefined && data[field.name] !== null) {
      switch (field.type) {
        case 'number':
          if (typeof data[field.name] !== 'number')
            throw new HttpException(`字段 ${field.label || field.name} 必须为数字`, HttpStatus.BAD_REQUEST)
          break
        case 'boolean':
          if (typeof data[field.name] !== 'boolean')
            throw new HttpException(`字段 ${field.label || field.name} 必须为布尔值`, HttpStatus.BAD_REQUEST)
          break
        case 'string':
        case 'text':
        default:
          if (typeof data[field.name] !== 'string')
            throw new HttpException(`字段 ${field.label || field.name} 必须为字符串`, HttpStatus.BAD_REQUEST)
      }
    }
  }
}
